from schemas.auth import GetTokenRequest, AuthBaseInfo
import hashlib
from urllib.request import Request
import time
from datetime import datetime, timezone, timedelta
from typing import Union


def verify(request: GetTokenRequest, authInfo: AuthBaseInfo):
    md5_hash = hashlib.md5()
    md5_string = "{}-{}-{}-{}".format(request.appId, authInfo.appSecret, authInfo.source, request.timestamp)

    md5_hash.update(md5_string.encode('utf-8'))

    return md5_hash.hexdigest().lower() == request.signed.lower()


def md5Encode(target: str):
    md5_hash = hashlib.md5()

    md5_hash.update(target.encode('utf-8'))

    return md5_hash.hexdigest()


def getRealClientIp(request: Request):
    clientIp = request.client.host
    forwardedFor = request.headers.get("x-forwarded-for")
    if forwardedFor:
        clientIp = forwardedFor.split(",")[0]

    return clientIp


def is_valid_timestamp(ts: Union[int, str, float],
                       max_future_delta: timedelta = timedelta(days=1),
                       enable_future_check: bool = True) -> bool:
    try:
        ts_float = float(ts)
    except (ValueError, TypeError):
        return False

    if ts_float < 0:
        return False

    if enable_future_check:
        now = time.time()
        if ts_float > now + max_future_delta.total_seconds():
            return False

        if ts_float < now - max_future_delta.total_seconds():
            return False

    try:
        datetime.fromtimestamp(ts_float, tz=timezone.utc)
    except (OSError, OverflowError, ValueError):
        return False

    return True
